home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
plan
/
src
/
weekdraw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
15KB
|
506 lines
/*
* week menu widgets.
*
* clicked_week_calendar(x, y) Press on the week display detected.
* draw_week_day(day, month, year) The day day/month/year has changed,
* redraw the week view if it contains
* that day.
* draw_week_calendar() If there is a week menu, resize, and
* redraw
* redraw_week_calendar() Same, but assume that it's still the
* same week, so don't recalc and resize.
*/
#include <time.h>
#include <Xm/Xm.h>
#include "cal.h"
#define DBLTIME 1000 /* doubleclick time [ms] */
#define SLOPE 1/4 /* slope of arrow head / barheight */
#define MINLEN 8 /* no bar is shorter than MINLEN */
#define TOD(t) ((t)%86400)
#define BOUND(t,a,b) ((t)<(a) ? (a) : (t)>(b) ? (b) : (t));
#define XPOS(t) (((t) - c->week_minhour*3600) * c->week_hourwidth/3600)
extern char *mktimestring(), *mkdatestring();
extern char *parse_holidays();
extern struct tm *time_to_tm();
extern time_t tm_to_time();
static draw_week_day_background();
static draw_week_day_foreground();
static draw_bar();
extern Display *display; /* everybody uses the same server */
extern GC jgc, gc; /* graphic context, Japanese and std */
extern XFontStruct *font[NFONTS]; /* fonts: FONT_* */
extern struct config config; /* global configuration data */
extern struct mainmenu mainmenu; /* all important main window widgets */
extern time_t curr_week; /* week being displayed, time in sec */
extern struct week week; /* info on week view */
extern struct list *mainlist; /* list of all schedule entries */
extern struct holiday holiday[366]; /* info for each day, separate for */
extern struct holiday sm_holiday[366];/* full-line texts under, and small */
extern char *weekday_name[];
extern char *monthname[];
/*
* got a click in the calendar area. Traverse the node tree, first down until
* the correct line is found, and then horizontally until the node is found.
*/
clicked_week_calendar(xc, yc, time)
int xc, yc; /* pixel pos clicked */
Time time; /* current time in ms */
{
register struct config *c = &config;
struct weeknode *vert, *horz; /* week node scan pointers */
register struct entry *ep; /* entry to test */
static struct entry *last_ep; /* last entry found (dblclk?)*/
static Time last_time; /* time of last press */
int d; /* day counter */
int yd; /* y start coord of day box */
int x, y; /* upper left of day bk box */
int ys; /* height of bar line w/ gaps*/
time_t btime; /* start time of bar */
int b, e; /* X start end end pos of bar*/
int xend; /* right margin of chart */
x = c->week_margin + c->week_daywidth + c->week_gap;
yd = 2*c->week_margin + c->week_title + c->week_hour + c->week_gap + 2;
ys = c->week_barheight + 2*c->week_bargap;
xend = x + c->week_hourwidth * (c->week_maxhour - c->week_minhour);
for (d=0; d < NDAYS; d++) {
for (y=yd, vert=week.tree[d]; vert; vert=vert->down, y+=ys) {
if (yc < y || yc >= y+ys)
continue;
if (xc < x) {
create_list_popup(mainlist, curr_week + d*86400,
86400, 0, 0);
return;
}
for (horz=vert; horz; horz=horz->next) {
draw_bar(horz, horz->user ? horz->user->color : 0,
x, y + c->week_bargap);
ep = horz->entry;
btime = TOD(ep->time);
if (config.weekwarn)
btime -= ep->early_warn > ep->late_warn
? ep->early_warn
: ep->late_warn;
if (btime < c->week_minhour*3600)
btime = c->week_minhour*3600;
e = b = x + XPOS(TOD(btime));
if (!ep->notime)
e += ep->length * c->week_hourwidth/3600;
if (e < b + MINLEN)
e = b + MINLEN;
if (!horz->textinside)
e += horz->textlen;
if (xc >= b && xc < e ||
xc >= xend-MINLEN && b >= xend) {
if (time-last_time < DBLTIME && ep == last_ep){
if (horz->user)
print_button(week.info,
"cannot edit");
else
create_list_popup(mainlist,
0, 0, 0, ep);
last_ep = 0;
return;
} else if (horz->user)
print_button(week.info, "%s (%s) %s",
mktimestring(ep->time, FALSE),
horz->user->name,
ep->note ? ep->note : "");
else
print_button(week.info, "%s %s",
mktimestring(ep->time, FALSE),
ep->note ? ep->note : "");
last_ep = ep;
last_time = time;
return;
}
}
}
yd += week.nlines[d] * ys + c->week_gap;
}
print_button(week.info, " ");
}
/*
* If the specified date is in the current week, redraw everything (something
* changed on the specified day).
*/
draw_week_day(day, month, year)
int day, month, year;
{
struct tm tm;
time_t date;
tm.tm_year = year;
tm.tm_mon = month;
tm.tm_mday = day;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
date = tm_to_time(&tm);
if (date >= curr_week && date < curr_week * NDAYS*86400) {
build_week();
draw_week_calendar();
}
}
/*
* draw the entire week menu, unconditionally. Calling create_week_menu
* will cause a callback to redraw_week_calendar, either explicitly or
* because of an expose event.
*/
draw_week_calendar()
{
if (!week.canvas)
return;
create_week_menu(); /* recalc & resize */
}
redraw_week_calendar()
{
register struct config *c = &config;
Window window;
char buf[40], *p;
XRectangle rects[25+2];
int i, l, x, y;
if (!week.canvas)
return;
window = XtWindow(week.canvas);
/* background */
set_color(COL_WBACK);
XFillRectangle(display, window, gc, 0, 0, week.canvas_xs,
week.canvas_ys);
strcpy(buf, mkdatestring(curr_week)); /* centered title */
strcat(buf, " - ");
strcat(buf, mkdatestring(curr_week + (NDAYS-1)*86400));
set_color(COL_WTITLE);
XSetFont(display, gc, font[FONT_WTITLE]->fid);
XDrawString(display, window, gc,
(week.canvas_xs - strlen_in_pixels(buf,FONT_WTITLE))/2,
c->week_margin + c->week_title * 3/4,
buf, strlen(buf));
for (i=0; i < NDAYS; i++) /* day background */
draw_week_day_background(i);
/* thick lines */
rects[0].x = c->week_margin;
rects[0].y = 2*c->week_margin + c->week_title + c->week_hour + 1;
rects[0].width = week.canvas_xs - 2*c->week_margin +1;
rects[0].height = 2;
rects[1].x = c->week_margin;
rects[1].y = week.canvas_ys - c->week_margin +2;
rects[1].width = week.canvas_xs - 2*c->week_margin +1;
rects[1].height = 2;
/* thin lines */
x = c->week_margin + c->week_daywidth + c->week_gap;
y = 2*c->week_margin + c->week_title + c->week_hour + 3;
for (i=0; i <= c->week_maxhour-c->week_minhour; i++) {
rects[i+2].x = x + i * c->week_hourwidth;
rects[i+2].y = y;
rects[i+2].width = 1;
rects[i+2].height = week.canvas_ys - c->week_margin -
rects[i+2].y + 3;
}
set_color(COL_WGRID);
XFillRectangles(display, window, gc, rects, i+2);
for (i=0; i < NDAYS; i++) /* day foreground */
draw_week_day_foreground(i);
/* hour labels */
set_color(COL_WDAY);
XSetFont(display, gc, font[FONT_WHOUR]->fid);
for (i=0; i <= c->week_maxhour-c->week_minhour; i++) {
p = mktimestring((i + c->week_minhour) * 3600, FALSE);
l = strlen_in_pixels(p, FONT_WHOUR);
XDrawString(display, window, gc,
x + i * c->week_hourwidth - l/2,
2*c->week_margin + c->week_title + c->week_hour -2,
p, strlen(p));
}
set_color(COL_STD);
}
/*
* draw the background of one day of the week at its position. This includes
* the day number and the box, but not the bars themselves. The bars are
* printed after the thin hour lines are drawn by the caller, by calling the
* following routine.
*/
static draw_week_day_background(wday)
int wday; /* day of the week, < NDAYS */
{
Window window = XtWindow(week.canvas);
register struct config *c = &config;
time_t today; /* today's date */
struct holiday *hp, *shp; /* to check for holidays */
char *errmsg; /* holiday parser error */
char buf[20]; /* holiday text buffer */
struct tm *tm; /* today's date as m/d/y */
char *p; /* temp for day name */
int x, y; /* upper left of day bk box */
int ys; /* height of bar line w/ gaps*/
int yt; /* text y position */
int yts; /* vert space for text */
int i;
if (week.nlines[wday] == 0)
return;
x = c->week_margin + c->week_daywidth + c->week_gap;
y = 2*c->week_margin + c->week_title + c->week_hour + c->week_gap + 2;
ys = c->week_barheight + 2*c->week_bargap;
for (i=0; i < wday; i++)
y += week.nlines[i] * ys + c->week_gap;
/* clear weekday name*/
yts = week.nlines[wday] * ys + c->week_gap -1;
today = get_time() - (curr_week + wday*86400);
set_color(today < 0 || today >= 86400 ? COL_WBACK : COL_CALTODAY);
XFillRectangle(display, window, gc, c->week_margin, y,
c->week_daywidth, yts);
/* weekday name */
yt = y + font[FONT_WDAY]->max_bounds.ascent;
i = (wday + 7 - c->sunday_first) % 7;
set_color(COL_WDAY);
XSetFont(display, gc, font[FONT_WDAY]->fid);
p = mkdatestring(curr_week + wday * 86400);
truncate_string(p, c->week_daywidth-2, FONT_WDAY);
XDrawString(display, window, gc, c->week_margin, yt, p, strlen(p));
yt += font[FONT_WDAY]->max_bounds.ascent +
font[FONT_WDAY]->max_bounds.descent;
/* holidays */
tm = time_to_tm(curr_week + wday*86400);
if (errmsg = parse_holidays(tm->tm_year, FALSE))
create_error_popup(mainmenu.cal, 0, errmsg);
shp = &sm_holiday[tm->tm_yday];
hp = &holiday[tm->tm_yday];
for (i=0; i < 2; i++, shp=hp)
if (shp->string && yt < y + yts) {
strncpy(buf, shp->string, sizeof(buf)-1);
truncate_string(buf, c->week_daywidth-2, FONT_WDAY);
set_color(shp->stringcolor ? shp->stringcolor :
shp->daycolor ? shp->daycolor
: COL_WDAY);
XDrawString(display, window, gc,
c->week_margin + c->week_daywidth-2 -
strlen_in_pixels(buf, FONT_WDAY),
yt, buf, strlen(buf));
yt += font[FONT_WDAY]->max_bounds.ascent +
font[FONT_WDAY]->max_bounds.descent;
}
/* appointment box */
set_color(COL_WBOXBACK);
XFillRectangle(display, window, gc, x, y,
week.canvas_xs - c->week_margin - x,
week.nlines[wday] * ys);
}
/*
* draw the foreground of one day of the week at its position. This includes
* all the bars. The background and the thin vertical lines have already been
* drawn by the caller.
*/
static draw_week_day_foreground(wday)
int wday; /* day of the week, < NDAYS */
{
register struct config *c = &config;
struct weeknode *vert, *horz; /* week node scan pointers */
int x, y; /* upper left of day bk box */
int ys; /* height of bar line w/ gaps*/
int i;
x = c->week_margin + c->week_daywidth + c->week_gap;
y = 2*c->week_margin + c->week_title + c->week_hour + c->week_gap + 2;
ys = c->week_barheight + 2*c->week_bargap;
for (i=0; i < wday; i++)
y += week.nlines[i] * ys + c->week_gap;
for (vert=week.tree[wday]; vert; vert=vert->down, y+=ys)
for (horz=vert; horz; horz=horz->next)
draw_bar(horz, horz->user ? horz->user->color : 0,
x, y + c->week_bargap);
}
/*
* draw one entry bar.
*/
static draw_bar(node, color, x, y)
struct weeknode *node; /* entry node to print */
int color; /* color, 0..7 */
int x, y; /* top left pos in canvas */
{
register struct entry *ep = node->entry;
register struct config *c = &config;
Window window = XtWindow(week.canvas);
int xend; /* right margin of chart */
int w[2], b, e; /* early/late, begin, end */
int ee; /* e with min length applied */
int i; /* warning counter, 0..1 */
int slope; /* delta-x of the arrowheads */
XPoint point[7]; /* polygon vertex list */
#ifdef JAPAN
int ji, jdeltax, plen;
XChar2b jstr[50];
strpack partialstr[MAXPARTIALSTRING];
unsigned char strpool[MAXPARTIALCHAR];
#endif
slope = c->week_barheight * SLOPE;
xend = x + c->week_hourwidth * (c->week_maxhour - c->week_minhour);
i = ep->early_warn > ep->late_warn;
w[!i] = TOD(ep->time) - ep->early_warn;
w[ i] = TOD(ep->time) - ep->late_warn;
b = TOD(ep->time);
e = TOD(ep->time) + (ep->notime ? 0 : ep->length);
w[0] = x + XPOS(w[0]);
w[1] = x + XPOS(w[1]);
b = x + XPOS(b);
e = x + XPOS(e);
ee = e < b+MINLEN ? b+MINLEN : e;
if (config.weekwarn && !ep->notime)
for (i=0; i < 2; i++)
if (w[i] < b && w[i] <= w[1] && b+slope > 0) {
point[5].x =
point[0].x =
point[2].x = BOUND(w[i]+slope, x, xend);
point[1].x = BOUND(w[i], x, xend);
point[3].x =
point[4].x = BOUND(b+slope, point[0].x, xend);
point[5].y =
point[0].y =
point[4].y = y;
point[1].y = y + c->week_barheight/2+1;
point[2].y =
point[3].y = y + (c->week_barheight&~1)+1;
set_color(COL_WWARN);
XFillPolygon(display, window, gc, point, 5,
Convex, CoordModeOrigin);
set_color(COL_WFRAME);
XDrawLines(display, window, gc, point, 6,
CoordModeOrigin);
}
point[6].x =
point[0].x =
point[2].x = BOUND(b+slope, x, xend);
point[1].x = BOUND(b, x, xend-MINLEN);
point[3].x = BOUND(ee-slope, point[0].x, xend);
point[3].x =
point[5].x = BOUND(point[3].x, point[1].x+MINLEN, xend);
point[4].x = BOUND(e, point[3].x, xend);
point[6].y =
point[0].y =
point[5].y = y;
point[1].y =
point[4].y = y + c->week_barheight/2+1;
point[2].y =
point[3].y = y + (c->week_barheight&~1)+1;
if (ep->notime)
point[3].x = point[5].x = point[0].x;
set_color(ep->suspended ? COL_WWARN : COL_WUSER_0 + color);
XFillPolygon(display, window, gc, point, 6, Convex, CoordModeOrigin);
set_color(COL_WFRAME);
XDrawLines(display, window, gc, point, 7, CoordModeOrigin);
if (*node->text) {
char buf[100];
strcpy(buf, node->text);
#ifdef JAPAN
partialstr->strptr = strpool;
if ((plen = mixedstrlen_in_pixels(node->text, partialstr,
FONT_WNOTE, FONT_JNOTE)) >
xend - x) {
for (plen = ji = 0; partialstr[ji].strptr != NULL &&
ji < MAXPARTIALSTRING; ji++) {
if (plen + partialstr[ji].pixlen > xend - x) {
/* Truncating*/
partialstr[ji].length *= (double)
(xend-x-plen)/(double)
partialstr[ji].pixlen;
plen = xend - x;
if (partialstr[ji].length == 0 ||
partialstr[ji].asciistr == False &&
(partialstr[ji].length &= ~1) == 0)
partialstr[ji].strptr = NULL;
break;
} else
plen += partialstr[ji].pixlen;
}
}
if (node->textinside) {
x = point[0].x;
x += (point[3].x-point[0].x - plen) / 2;
if (x + plen > xend-plen)
x = xend-1 - plen;
} else
x = point[4].x + 3;
#else
if (node->textinside) {
int l;
x = point[0].x;
truncate_string(buf, xend - x, FONT_WNOTE);
l = strlen_in_pixels(buf, FONT_WNOTE);
x += (point[3].x-point[0].x - l) / 2;
if (x + l > xend-1)
x = xend-1 - l;
} else {
x = point[4].x + 3;
truncate_string(buf, xend - x, FONT_WNOTE);
}
#endif
set_color(COL_WNOTE);
XSetFont(display, gc, font[FONT_WNOTE]->fid);
#ifdef JAPAN
XSetFont(display, jgc, font[FONT_JNOTE]->fid);
for (ji = 0, jdeltax = x; partialstr[ji].strptr != NULL &&
ji < MAXPARTIALSTRING; ji++) {
if (partialstr[ji].asciistr == True)
XDrawString(display, window, gc,
jdeltax, y + c->week_barheight/2 +
font[FONT_WDAY]->max_bounds.ascent/2,
partialstr[ji].strptr,
partialstr[ji].length);
else
XDrawString16(display, window, jgc,
jdeltax, y + c->week_barheight/2 +
font[FONT_WDAY]->max_bounds.ascent/2,
(XChar2b *)partialstr[ji].strptr,
partialstr[ji].length/2);
jdeltax += partialstr[ji].pixlen;
}
#else
XDrawString(display, window, gc,
x, y + c->week_barheight/2
+ font[FONT_WDAY]->max_bounds.ascent/2,
buf, strlen(buf));
#endif
}
}